/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.uca.dss.curso2011.grupo1.clases;

import java.util.List;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.uca.dss.curso2011.grupo1.basededatos.DBUtils;

/**
 * Clase que implementa el control de la reservas de los viajes.
 * @author Alejandro
 */
public class ControlaReserva {

         private List<Hora> horas;
         private List<Reserva> reservas;
         private List<InformacionReserva> informacionesReservas;
         private RepartoAsientos repartoAsientos;

         /**
          * Constructor de la clase ControlaReserva.
          * @param horas Lista de horas a las que hay trayectos.
          * @param reservas Lista de reservas registradas.
          * @param informacionesReservas Lista de las horas reservadas para los viajes.
          * @param repartoAsientos Criterio de asiganción de los asientos.
          */

        public ControlaReserva (List<Hora> horas,List<Reserva> reservas, List<InformacionReserva> informacionesReservas,RepartoAsientos repartoAsientos){
            this.horas = horas;
            this.reservas = reservas;
            this.informacionesReservas = informacionesReservas;
            this.repartoAsientos = repartoAsientos;

        }

     /**
     * Permite realizar una reserva del viaje
     *
     * En el caso de que alguno de los parámetros no sea correcto, debe de devolver
     * una excepción IllegalArgumentException
     *
     * @param origen ciudad de origen
     * @param destino ciudad de destino
     * @param fecha fecha del viaje
     * @param hora hora del viaje
     * @return cadena que identifica a la reserva. Puede ser cualquier cadena
     *
     */
    public String reservaAsiento(String origen, String destino, LocalDate fecha, LocalTime hora){
        // Por cada hora mira si tiene un trayecto con esa ciudad de origen y destino, en caso afirmativo lo guarda.
            for(Hora horita : this.horas){
                if(horita.obtieneTrayecto().existeTrayecto(new Ciudad(origen),new Ciudad(destino)) != false){
                    if(horita.obtieneHoraSalida().equals(hora)){
                        //Encontramos la hora buscada, y miramos si esta ya creada para la fecha, como InformacionReserva.
                        boolean horaRCreada = false;
                        InformacionReserva horaRegistrada = null;
                        for(InformacionReserva horaR : this.informacionesReservas){
                            if(horaR.comparaInformacionReserva(horita, fecha)){
                                horaRCreada = true;
                                horaRegistrada = horaR;
                            }    
                        }
                        //Si no existe el objeto InformacionReserva para esa fecha, creamos el objeto, y lo añadimos a la lista.
                        if(!horaRCreada){
                            horaRegistrada = new InformacionReserva(horita,fecha);
                            this.informacionesReservas.add(horaRegistrada);
                        }
                        //Creamos la reserva 
                        Reserva reservaEnTramite = new Reserva(horaRegistrada,this.repartoAsientos);

                        //La añadimos a la lista de reservas.
                        this.reservas.add(reservaEnTramite);

                        //Almacenamos en la base de datos la reserva.
                        DBUtils.getDb().store(reservaEnTramite);

                        return reservaEnTramite.obtieneCodigoReserva();
                    }
                }
            }
        throw new RuntimeException("reservaAsiento:No existe el trayecto dada en esa hora");
  
    }
    /**
     * Cancela una reserva, dejando el asiento indicado libre
     * @param codigoReserva cadena que identifica la reserva
     */
    public void cancelaReserva(String codigoReserva){
        int asiento;

        //Buscamos la reserva con dicho código.
        if(!this.reservas.isEmpty()){
            boolean existeReserva = false;
            for(Reserva reserva : this.reservas){
                if(reserva.obtieneCodigoReserva().equals(codigoReserva)){
                    //Obtenemos el asiento, para liberar la plaza.

                    reserva.cancelaAsientoReserva();

                     //Eliminamos de la base de datos
                    DBUtils.getDb().delete(reserva);
                    
                    //Eliminamos la reserva.
                    this.reservas.remove(reserva);


                    existeReserva = true;
                    break;
                }
            }
            if(!existeReserva){
                throw new RuntimeException("cancelaReserva:El código de la reserva no es válido.");
            }
        }else{
          throw new RuntimeException("cancelaReserva:No existen reservas.");
        }
    }
     /**
     * Devuelve el precio de la reserva del viaje
     * @param origen ciudad de origen
     * @param destino ciudad de destino
     * @param fecha fecha del viaje
     * @param hora hora del viaje
     * @return precio de una reserva del viaje
     */
    public double obtienePrecio(String origen, String destino, LocalDate fecha, LocalTime hora){
         // Por cada hora mira si tiene un trayecto con esa ciudad de origen y destino, en caso afirmativo lo guarda.
            for(Hora horita : this.horas){
                if(horita.obtieneTrayecto().existeTrayecto(new Ciudad(origen),new Ciudad(destino)) != false){
                    if(horita.obtieneHoraSalida().equals(hora)){
                    //Devolvemos el precio.
                    return horita.calculaPrecio();
                    }
                }
            }
            throw new RuntimeException("getPrecio:No existe el trayecto a esa hora");
    }
    /**
     * Devuelve el número de asientos libres de un medio de transporte para un trayecto en la fecha dada.
     * @param origen Ciudad de origen.
     * @param destino Ciudad de destino.
     * @param fecha Fecha del viaje.
     * @param hora Hora del viaje.
     * @return Número de asientos libres.
     */
    public int asientosLibres(String origen, String destino, LocalDate fecha, LocalTime hora){
        // Por cada hora mira si tiene un trayecto con esa ciudad de origen y destino, en caso afirmativo lo guarda.
            for(Hora horita : this.horas){
                if(horita.obtieneTrayecto().existeTrayecto(new Ciudad(origen),new Ciudad(destino)) != false){
                    if(horita.obtieneHoraSalida().equals(hora)){
                        //Encontramos la hora buscada, y miramos si esta ya creada para la fecha, como InformacionReserva.
                        boolean horaRCreada = false;
                        InformacionReserva horaRegistrada = null;
                        for(InformacionReserva horaR : this.informacionesReservas){
                            if(horaR.comparaInformacionReserva(horita, fecha)){
                                horaRCreada = true;
                                horaRegistrada = horaR;
                            }
                        }
                        //Si no existe el objeto InformacionReserva para esa fecha, devolvemos el tamaño del medio de transporte, ya que no existe ninguna reserva para esa fecha con esa hora.
                        if(!horaRCreada){
                            return horita.obtieneMedioTransporte().obtieneNumeroAsientos();
                        }
                        //Si existe, pues calculamos el número de asientos libres.

                        return horaRegistrada.numeroAsientosLibres();
                    }
                }
            }
            throw new RuntimeException("asientosLibres:No existe un trayecto entre las ciudades dadas a la hora indicada");
    }

}
